package com.renfei.multimediatask.ui.task7;

import android.icu.text.IDNA;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.nfc.Tag;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.webkit.PermissionRequest;
import android.widget.Button;
import android.widget.RelativeLayout;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.renfei.multimediatask.R;
import com.renfei.multimediatask.base.BaseActivity;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class AudioAacDecodecActivity extends BaseActivity {
    @BindView(R.id.startDecodecAndPlay)
    Button startDecodecAndPlay;
    @BindView(R.id.ll_btn_layout)
    RelativeLayout llBtnLayout;
    private String targetFilePath;


    private DecodecAACFileThrea decodecAACFileThrea;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_audio_aac_decodec;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void initListener() {
        targetFilePath = getParentFilePath() + "audio_aac_encodec.aac";
        decodecAACFileThrea = new DecodecAACFileThrea(new WeakReference<>(this));

    }


    @OnClick(R.id.startDecodecAndPlay)
    public void onViewClicked() {
        decodecAACFileThrea.start();
    }


    static class DecodecAACFileThrea extends Thread {
        //等待超时时间
        private static final int TIMEOUT_US = 1000;

        private static final String TAG = DecodecAACFileThrea.class.getSimpleName();
        private WeakReference<AudioAacDecodecActivity> weakReference;


        /**
         * 音频分解器
         */
        private MediaExtractor mediaExtractor;
        private final String audioType = "audio/";
        private final String mineType = MediaFormat.MIMETYPE_AUDIO_AAC;
        private MediaFormat audio_format;

        //通过多媒体分解器 获取以下信息
//        private int key_bit_rate;
        private int key_channel_count;
        private int key_sample_rate;
        private int sampleRateType;


        /**
         * 使用多媒体文件的源参数，设置解码器的参数
         */
        private MediaCodec audioDecodec;

        private MediaCodec.BufferInfo audioBufferInfo;
        /**
         * audioTrack播放
         */
        private AudioTrack audioTrack;
        private int streamType = AudioManager.STREAM_MUSIC;//音频管理策略  铃声，系统铃声，警告声，音乐声
        private int mode = AudioTrack.MODE_STREAM;


        private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;   //采样格式(存储位数， 8位 16位)
        //使用audioTrack播放时，声道格式  与录制时 设置格式是不同的
        private int channelConfig = AudioFormat.CHANNEL_OUT_MONO;   //声道数


        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        public DecodecAACFileThrea(WeakReference<AudioAacDecodecActivity> weakReference) {
            this.weakReference = weakReference;

            audioBufferInfo = new MediaCodec.BufferInfo();
            initMediaExector();
        }


        /**
         * 初始化多媒体分解器
         * <p>
         * 提取媒体文件的各个参数来设置 mediaCodec  解码器参数
         */
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        private void initMediaExector() {
            try {
                mediaExtractor = new MediaExtractor();
                mediaExtractor.setDataSource(weakReference.get().targetFilePath);

                //使用
                int trackCount = mediaExtractor.getTrackCount();
                for (int i = 0; i < trackCount; i++) {
                    MediaFormat mediaFormat = mediaExtractor.getTrackFormat(i);
                    String mine = mediaFormat.getString(MediaFormat.KEY_MIME);
                    if (mine.startsWith(audioType)) {
                        mediaExtractor.selectTrack(i);
                        audio_format = mediaExtractor.getTrackFormat(i);


//                        key_bit_rate = audio_format.getInteger(MediaFormat.KEY_BIT_RATE);
                        key_channel_count   = audio_format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
                        key_sample_rate     = audio_format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                        sampleRateType      = ADTSUtils.getSampleRateType(key_sample_rate);

                        //创建解码器
                        audioDecodec = MediaCodec.createDecoderByType(mine);
                        audioDecodec.configure(audio_format, null, null, 0);

                        int bufferSizeInBytes = AudioTrack.getMinBufferSize(key_sample_rate,
                                channelConfig,
                                audioFormat);
                        audioTrack = new AudioTrack(
                                streamType, key_sample_rate, channelConfig, audioFormat, bufferSizeInBytes, mode
                        );

                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            }


        }


        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void run() {
            super.run();


            if (audioDecodec == null) {
                Log.e(TAG, "create mediaDecode failed");
                return;
            }
            audioDecodec.start();//启动MediaCodec ，等待传入数据

            audioTrack.play();

            int sampleSize = 0;

            int maxVideoBufferCount = audio_format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
            ByteBuffer readBuffer = ByteBuffer.allocate(maxVideoBufferCount);

            while ((sampleSize = mediaExtractor.readSampleData(readBuffer, 0)) >= 0) {
                //获取可用的inputBuffer -1代表一直等待，0表示不等待 建议-1,避免丢帧
                int inputBufferIndex = audioDecodec.dequeueInputBuffer(-1);
                if (inputBufferIndex > 0) {
                    ByteBuffer inputBuffer = audioDecodec.getInputBuffer(inputBufferIndex);
                    inputBuffer.clear();
                    inputBuffer.put(readBuffer);

                    audioDecodec.queueInputBuffer(
                            inputBufferIndex,
                            0, sampleSize,
                            mediaExtractor.getSampleTime(),
                            0
                    );
                }
                mediaExtractor.advance();

                int outputBufferIndex = audioDecodec.dequeueOutputBuffer(audioBufferInfo, TIMEOUT_US);

                Log.e(TAG, "outputBufferIndex    " + outputBufferIndex);
                switch (outputBufferIndex) {
                    case MediaCodec.INFO_TRY_AGAIN_LATER:
                        Log.d(TAG, "dequeueOutputBuffer timed out!");
                        break;
                    case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                        MediaFormat format = audioDecodec.getOutputFormat();
                        Log.d(TAG, "New format " + format);
                        audioTrack.setPlaybackRate(format.getInteger(MediaFormat.KEY_SAMPLE_RATE));
                        break;
                    case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:

                        break;
                    default:
                        ByteBuffer outputBuffer = audioDecodec.getOutputBuffer(outputBufferIndex);

                        final byte[] chunk = new byte[audioBufferInfo.size];
                        outputBuffer.get(chunk);

                        audioTrack.write(chunk, audioBufferInfo.offset, audioBufferInfo.offset + audioBufferInfo.size);

                        outputBuffer.clear();
                        audioDecodec.releaseOutputBuffer(outputBufferIndex, false);
                        break;
                }


            }
            mediaExtractor.release();


            audioDecodec.stop();
            audioTrack.stop();
        }


        public void release() {
            audioDecodec.release();
            audioTrack.release();
        }
    }


}
